#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/slab.h>

#define SET_FAN_PWM _IOR('f', 1, int)
#define SET_MATOR_PWM _IOR('m', 1, int)
#define SET_BEEP_PWM _IOR('b', 1, int)

#define PWM_MAX 10000
int pwm = 0;
struct pwm_device *pwm_fan = NULL, *pwm_mator = NULL, *pwm_beep = NULL;
struct pwm_state state;
#define CNAME "pwm-fan"
char kbuf[16] = "";
// 分布实现字符设备相关
struct cdev* cdev = NULL;
dev_t devn = -1;

// 自动创建设备节点相关
struct class* cls = NULL;
struct device* dev = NULL;

ssize_t my_write(struct file* file, const char __user* ubuf, size_t size, loff_t* loffs)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    if (copy_from_user(kbuf, ubuf, sizeof(pwm))) {
        printk("__%d__:copy_from_user is error\n", __LINE__);
        return -1;
    }
    switch (kbuf[0]) {
    case '1':
        pwm = PWM_MAX / 5 * 1;
        break;
    case '2':
        pwm = PWM_MAX / 5 * 2;
        break;
    case '3':
        pwm = PWM_MAX / 5 * 3;
        break;
    case '4':
        pwm = PWM_MAX / 5 * 4;
        break;
    case '5':
        pwm = PWM_MAX;
        break;
    }
    state.duty_cycle = pwm;
    pwm_apply_state(pwm_fan, &state);
    pwm_apply_state(pwm_mator, &state);
    printk("pwm = %d\n", pwm);
    return size;
}

long my_ioctl(struct file* file, unsigned int cmd, unsigned long args)
{
    switch (cmd) {
    case SET_FAN_PWM:
        pwm = PWM_MAX / 100 * args;
        state.duty_cycle = pwm;
        pwm_apply_state(pwm_fan, &state);
        break;
    case SET_BEEP_PWM:
        pwm = PWM_MAX / 100 * args;
        state.duty_cycle = pwm;
        pwm_apply_state(pwm_beep, &state);
        break;
    case SET_MATOR_PWM:
        pwm = PWM_MAX / 100 * args;
        state.duty_cycle = pwm;
        pwm_apply_state(pwm_mator, &state);
        break;
    }

    return 0;
}
int my_close(struct inode* inode, struct file* file)
{
    pwm_disable(pwm_mator);
    pwm_disable(pwm_fan);
    pwm_disable(pwm_beep);
    return 0;
}
const struct file_operations fops = {
    .unlocked_ioctl = my_ioctl,
    .write = my_write,
    .release = my_close,
};
static int my_pwm_probe(struct platform_device* pdev)
{
    struct device_node* fan_node;
    struct device_node* mator_node;
    struct device_node* beep_node;
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    // 获取风扇节点
    fan_node = of_find_node_by_path("/fan");
    if (!fan_node) {
        printk("__%d__:of_find_node_by_path is error\n", __LINE__);
        return -1;
    }
    // 获取马达节点
    mator_node = of_find_node_by_path("/vibrator");
    if (!fan_node) {
        printk("__%d__:of_find_node_by_path is error\n", __LINE__);
        return -1;
    }
    // 获取蜂鸣器节点
    beep_node = of_find_node_by_path("/beeper");
    if (!fan_node) {
        printk("__%d__:of_find_node_by_path is error\n", __LINE__);
        return -1;
    }
    // 获取马达PWM
    pwm_mator = devm_of_pwm_get(&pdev->dev, mator_node, NULL);
    if (IS_ERR(pwm_mator)) {
        printk("__%d__:devm_of_pwm_get is error\n", __LINE__);
        return PTR_ERR(pwm_mator);
    }
    // 获取风扇PWM
    pwm_fan = devm_of_pwm_get(&pdev->dev, fan_node, NULL);
    if (IS_ERR(pwm_fan)) {
        printk("__%d__:devm_of_pwm_get is error\n", __LINE__);
        return PTR_ERR(pwm_fan);
    }
    // 获取蜂鸣器PWM
    pwm_beep = devm_of_pwm_get(&pdev->dev, beep_node, NULL);
    if (IS_ERR(pwm_beep)) {
        printk("__%d__:devm_of_pwm_get is error\n", __LINE__);
        return PTR_ERR(pwm_beep);
    }
    pwm_init_state(pwm_fan, &state);
    pwm_init_state(pwm_beep, &state);
    pwm_init_state(pwm_mator, &state);
    state.period = PWM_MAX;
    state.duty_cycle = pwm;
    state.enabled = true;

    /**********分布实现字符设备**************/
    cdev = cdev_alloc();
    if (!cdev) {
        printk("__%d__:cdev_alloc is error\n", __LINE__);
        goto ERR1;
    }
    cdev_init(cdev, &fops); // 初始化对象
    // 动态分配对象
    if (alloc_chrdev_region(&devn, 0, 1, CNAME)) {
        printk("__%d__:alloc_chrdev_region is error\n", __LINE__);
        goto ERR2;
    }
    // 注册对象
    if (cdev_add(cdev, devn, 1)) {
        printk("__%d__:cdev_add is error\n", __LINE__);
        goto ERR3;
    }
    /**********自动创建设备节点**************/
    cls = class_create(THIS_MODULE, CNAME);
    if (IS_ERR(cls)) {
        printk("__%d__:class_create is error\n", __LINE__);
        goto ERR4;
    }
    dev = device_create(cls, NULL, devn, NULL, CNAME);
    if (IS_ERR(dev)) {
        printk("__%d__:device_create is error\n", __LINE__);
        goto ERR5;
    }
    return 0;

ERR5:
    class_destroy(cls);
ERR4:
    cdev_del(cdev);
ERR3:
    unregister_chrdev_region(devn, 1);
ERR2:
    kfree(cdev);
ERR1:
    return -1;
    return 0;
}

static int my_pwm_remove(struct platform_device* pdev)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    pwm_disable(pwm_fan);
    pwm_disable(pwm_mator);
    pwm_disable(pwm_beep);
    pwm_free(pwm_fan);
    pwm_free(pwm_mator);
    pwm_free(pwm_beep);

    device_destroy(cls, devn);
    class_destroy(cls);

    cdev_del(cdev); // 注销对象
    unregister_chrdev_region(devn, 1);
    kfree(cdev);
    return 0;
}

static const struct of_device_id my_pwm_of_match[] = {

    {
        .compatible = "hqyj,fan",
    },

    {},
};
MODULE_DEVICE_TABLE(of, my_pwm_of_match);

static struct platform_driver my_pwm_driver = {
    .driver = {
        .name = "my_pwm_driver",
        .of_match_table = my_pwm_of_match,
    },
    .probe = my_pwm_probe,
    .remove = my_pwm_remove,
};

module_platform_driver(my_pwm_driver);
MODULE_LICENSE("GPL");